package com.mxf.example.exception;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by mxf on 2020/7/29.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 处理自定义的业务异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public  ErrorBody bizExceptionHandler(HttpServletRequest req, BizException e){
        logger.error("发生业务异常！原因是：{}",e.getErrorMsg());
        return ErrorBody.error(e.getErrorCode(),e.getErrorMsg());
    }

    /**
     * 处理空指针的异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseBody
    public ErrorBody exceptionHandler(HttpServletRequest req, NullPointerException e){
        logger.error("发生空指针异常！原因是:",e);
        return ErrorBody.error(ResultEnum.INTERNAL_SERVER_ERROR);
    }

    /**
     * 处理认证的业务异常
     * @param response
     * @param req
     * @param authenticationException
     * @return
     */
    @ExceptionHandler(value = AuthenticationException.class)
    @ResponseBody
    public  ErrorBody AuthExceptionHandler(HttpServletResponse response,HttpServletRequest req, AuthenticationException authenticationException){
        logger.error("认证发生异常！原因是：{}",authenticationException.getMessage());
        if (authenticationException instanceof UsernameNotFoundException || authenticationException instanceof BadCredentialsException) {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "用户名或密码错误"));
        } else if (authenticationException instanceof DisabledException) {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "用户已被禁用"));
        } else if (authenticationException instanceof LockedException) {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "账户被锁定"));
        } else if (authenticationException instanceof AccountExpiredException) {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "账户过期"));
        } else if (authenticationException instanceof CredentialsExpiredException) {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "证书过期"));
        } else {
            return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, "token无效"));
        }
    }
    /**
     * 处理授权的业务异常
     * @param response
     * @param req
     * @param authenticationException
     * @return
     */
    @ExceptionHandler(value = AccessDeniedException.class)
    @ResponseBody
    public  ErrorBody AccessExceptionHandler(HttpServletResponse response,HttpServletRequest req, AccessDeniedException authenticationException){
        logger.error("授权发生异常！原因是：{}",authenticationException.getMessage());
        return (ErrorBody.error(HttpServletResponse.SC_UNAUTHORIZED, ResultEnum.NOT_EXTENDED.getResultMsg()));
    }
    /**
     * 处理参数校验的业务异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public  ErrorBody validationExceptionHandler(HttpServletRequest req, ConstraintViolationException e){
        List msg = new ArrayList<>();
        e.getConstraintViolations().forEach(error -> {
            msg.add(error.getMessage()+":"+error.getPropertyPath().toString());
        });
        logger.error("参数异常！原因是：{}",JSON.toJSONString(msg));

        return ErrorBody.error(ResultEnum.INTERNAL_SERVER_ERROR.getResultCode(),JSON.toJSONString(msg));
    }
    /**
     * 处理其他异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public ErrorBody exceptionHandler(HttpServletRequest req, Exception e){
        logger.error("未知异常！原因是:",e);
        return ErrorBody.error(ResultEnum.INTERNAL_SERVER_ERROR);
    }

}
